Activity 启动流程和 UML 时序图

本文以启动的目标 Activity 所属进程不存在的情形为例,结合 Android12 源码,给出了整个过程的流程图,以及局部过程的时序图。推荐一个 Android 源码阅读网站

先附上一张整体过程的流程图。app1 是当前活动的 Activity 所在的应用进程,图示为浅蓝色,app2 是即将启动的 Activity 进程,图示为深蓝色,系统进程主要为 AM(黄色) 和 WM(红色),涉及到的代码路径包括:

/frameworks/base/core/java/android/app/...
/frameworks/base/services/core/java/com/android/server/wm/...
/frameworks/base/services/core/java/com/android/server/am/...

在这里插入图片描述
如图所示,启动 Activity 过程主要分为 5 个流程。

  1. app1 进程发起启动另一个应用中的 Activity 的请求;
  2. WM 对发送过来的 intent 参数进行解析,选择启动模式,并校验启动权限、参数合法性。如果校验通过,就通知 app1 中当前的活动 Activity 暂停;
  3. app1 收到系统暂停当前 Activity 的要求,执行相关过程,并告知系统已暂停;
  4. 继续执行目标 Activity 启动的过程,首先进行任务栈相关的处理。因为目标 Activity 所在进程不存在,所以首先要通过 AMS 创建 app2 进程,绑定资源和上下文环境;
  5. 创建并启动目标 Activity

在后文中跳过了步骤 3 中 pause 当前 Activity 的具体流程,以及步骤 4 中 zygote fork 进程的过程,把注意力集中到了 Activity 启动过程上。

1、app1 发起 Activity 启动请求

在这里插入图片描述
比较典型的点击桌面上应用图标启动 Activity 这个场景,桌面自身也是一个 Activity,当点击事件发生后,这个 Activity 会调用到 Activity.java 的 startActivity() 方法,开始启动目标 Activity 的流程。在 Activity.java 中经过几次调用后会调用到 Instrumentain 类中的 execStartActivity() 方法。

Instrumentation 翻译为仪表盘,顾名思义,它的作用是监视 app 进程与系统间的交互,比如 Activity 和 Application 的生命周期。每个 Activity 都持有一个 Instrumentation 对象的引用,但一个应用进程只有一个 Instrumentation 对象。如下是 Instrumentation.java 中 execStartActivity 的核心逻辑:

1853      public ActivityResult execStartActivity(
1854          Context who, IBinder contextThread, IBinder token, String target,
1855          Intent intent, int requestCode, Bundle options) {
   
              ...
1882              int result = ActivityTaskManager.getService().startActivity(whoThread,
1883                      who.getOpPackageName(), who.getAttributionTag(), intent,
1884                      intent.resolveTypeIfNeeded(who.getContentResolver()), token, target,
1885                      requestCode, 0, null, options);
              ...
1891      }

其中,ActivityTaskManager.getService() 会获取 IActivityTaskManager 对象,它是ActivityTaskManagerService 的代理,也就是一个用于跨进程通信的 Binder。所以这里其实是跨进程调用到 WM 中 ActivityTaskManager.java 的 startActivity() 方法。

2、WM 中解析和校验启动参数、模式,处理任务栈

在这里插入图片描述
上图里跳过了 pause 当前活动 Activity 的具体过程,只以 startPausingLocked 带过。

首先,ActivityTaskManagerService.java 经过几次调用会走到如下的 startActivityAsUser() 方法。

1178      private int startActivityAsUser(IApplicationThread caller, String callingPackage,
1179              @Nullable String callingFeatureId, Intent intent, String resolvedType,
1180              IBinder resultTo, String resultWho, int requestCode, int startFlags,
1181              ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
   
              ...
1188          // TODO: Switch to user app stacks here.
1189          return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
1190                  .setCaller(caller)
1191                  .setCallingPackage(callingPackage)
1192                  .setCallingFeatureId(callingFeatureId)
1193                  .setResolvedType(resolvedType)
1194                  .setResultTo(resultTo)
1195                  .setResultWho(resultWho)
1196                  .setRequestCode(requestCode)
1197                  .setStartFlags(startFlags)
1198                  .setProfilerInfo(profilerInfo)
1199                  .setActivityOptions(bOptions)
1200                  .setUserId(userId)
1201                  .execute();
1202  
1203      }

其中,getActivityStartController().obtainStarter() 会通过 Starter 池获取到一个 ActivityStarter 对象,在设置 caller 的一些参数后执行 ActivityStarter 的 execute 方法。

ActivityStarter 会将 intent 和 flag 转换为 Activity 的启动逻辑,决定 Activity 如何启动,如何处理相关的任务和栈。

811      private int executeRequest(Request request) {
   
              ...
1177          mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值